#pragma once

#include <iostream>
#include <cstring>
#include <string>
#include <sys/epoll.h>
#include "Err.hpp"
#include "Log.hpp"

static const int defaultepfd = -1;
static const int size = 128;

class Epoller
{
public:
    Epoller(int epfd = defaultepfd)
        : _epfd(epfd)
    {
    }
    ~Epoller()
    {
        if (_epfd != defaultepfd)
            close(_epfd);
    }

public:
    void Create()
    {
        _epfd = epoll_create(size);
        if (_epfd < 0)
        {
            logMessage(FATAL, "epoll_create error, code: %d, errstring: %s", errno, strerror(errno));
            exit(EPOLL_CREATE_ERR);
        }
        logMessage(NORMAL, "epoll_create success");
    }

    // user -> kernel
    // 其次将sock与它要关心的事件"写透式"注册到epoll中，让epoll帮我们关心
    bool AddEvent(int sock, uint32_t events)
    {
        struct epoll_event ev;
        ev.data.fd = sock;
        ev.events = events;
        int n = epoll_ctl(_epfd, EPOLL_CTL_ADD, sock, &ev);
        return n == 0;
    }

    // kernel -> user
    int Wait(struct epoll_event revs[], int num, int timeout)
    {
        int n = epoll_wait(_epfd, revs, num, timeout);
        return n;
    }

    bool Control(int sock, uint32_t event, int action)
    {
        int n = 0;
        if (action == EPOLL_CTL_MOD)
        {
            struct epoll_event ev;
            ev.data.fd = sock;
            ev.events = event;
            n = epoll_ctl(_epfd, EPOLL_CTL_MOD, sock, &ev);
        }
        else if (action == EPOLL_CTL_DEL)
        {
            n = epoll_ctl(_epfd, EPOLL_CTL_DEL, sock, nullptr);
        }
        else
            return n = -1;
        return n == 0;
    }

    void Close()
    {
        if (_epfd > 0)
            close(_epfd);
    }

private:
    int _epfd;
};